<!DOCTYPE html>
<html>

<head>
    <title></title>
    <style>
        body {
            margin: 0;
        }

        .box {
            display: flex;
            justify-content: flex-start;
            flex-wrap: wrap;
        }

        .card {
            flex: 1;
            min-width: 26%;
            max-width: calc(33.3% - 40px);
            height: 200px;
            margin: 30px 10px;
            position: relative;
            padding: 10px;
            box-shadow: 0 2px 5px 0 #999;
            border-radius: 5px;
            border: 2px dashed transparent;
        }

        .card-name {
            position: absolute;
            top: 10px;
            left: 10px;
            line-height: 20px;
            height: 20px;
        }

        .card-img {
            position: relative;
            padding-top: 20px;
            box-sizing: border-box;
            width: 100%;
            height: 100%;
            overflow: hidden;
        }

        .card-img img {
            width: 100%;
            height: 100%;
        }

        .dragging-over * {
            pointer-events: none;
        }
    </style>
</head>

<body>
<div class="box">
</div>
</body>
<script>
    const htmlArr = [
        {
            title: '示例1-风景',
            src: 'https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=2756575517,833879878&fm=200&gp=0.jpg'
        },
        {
            title: '示例2-风景',
            src: 'https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=328517395,2303970886&fm=26&gp=0.jpg'
        },
        {
            title: '示例3-风景',
            src: 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1554369684535&di=1c1dbfbd4545ad0a05e12cbbbfe3eeef&imgtype=0&src=http%3A%2F%2Fpic41.nipic.com%2F20140601%2F18681759_143805185000_2.jpg'
        },
        {
            title: '示例4-风景',
            src: 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1554369684534&di=d6e34af6fce6564f9df6c4eecc27d2ce&imgtype=0&src=http%3A%2F%2Fimgsrc.baidu.com%2Fimgad%2Fpic%2Fitem%2F4d086e061d950a7b9138ff1000d162d9f3d3c9d1.jpg'
        },
    ]

    let fromDom = null,
        toDom = null,
        lastDom = null;

    function handleDragStart(e, dom) {
        lastDom = fromDom = dom;
        dom.style.border = "2px dashed #0a0";
        dom.style.opacity = 0.4;
    }

    function handleDrop(e, dom) {
        //只有在可放置的元素上面松开鼠标才会触发drop事件
        console.log('drop');
        dom.style.opacity = "";
        swapDom(fromDom, lastDom);
        fromDom = null;
        toDom = null;
    }

    function handleDragEnd(e, dom) {
        //拖拽时松开鼠标就会会触发dragend事件
        console.log('end');
        dom.style.border = "2px dashed transparent";
        dom.style.opacity = "";
        toDom = null;
    }
    function handleDragleave(e, dom) {
        dom.style.border = "2px dashed #FFF";
        toDom = dom;
        if (fromDom == lastDom) {
            //第一次调换
            // swapDom(lastDom, toDom);
            lastDom = toDom;
        } else {
            //第N+1次调换，要先把上一个div的东西还原回去，再跟第三个div互换
            //这个防止enter多次触发
            if (lastDom == toDom) {
                return;
            }
            // swapDom(fromDom, lastDom);
            // swapDom(fromDom, toDom);
            lastDom = toDom;
        }
    }
    function handleDragEnter(e, dom) {
        dom.style.border = "2px dashed #d99";
        toDom = dom;
        if (fromDom == lastDom) {
            //第一次调换
            swapDom(lastDom, toDom);
            lastDom = toDom;
        } else {
            //第N+1次调换，要先把上一个div的东西还原回去，再跟第三个div互换
            //这个防止enter多次触发
            if (lastDom == toDom) {
                return;
            }
            swapDom(fromDom, lastDom);
            swapDom(fromDom, toDom);
            lastDom = toDom;
        }
    }

    function handleDragOver(e, dom) {
        dom.style.border = "2px dashed #d99";
        //默认无法把元素放置到其他元素当中，所以需要prevent
        e.preventDefault();
        e.dataTransfer.effectAllowed = "move";
    }

    function swapDom(a, b) {
        //a和b的innerHTML互换
        let temp = a.innerHTML;
        a.innerHTML = b.innerHTML;
        b.innerHTML = temp;
    }

    //生成dom结构
    function createDom(arr) {
        let body = document.getElementsByClassName('box')[0];
        let html = [];
        for (let i = 0, len = arr.length; i < len; i++) {
            html.push(template(arr[i].title, arr[i].src));
        }
        body.innerHTML = html.join('');
    }

    //html模板，根据该模板动态生成dom节点
    function template(title, src) {
        let tpl = `<div class="card"
draggable="true"

ondragstart="handleDragStart(event,this)"
 ondragover="handleDragOver(event,this)"
 ondragend="handleDragEnd(event,this)"
 ondrop="handleDrop(event,this)"
 ondragleave="handleDragleave(event,this)"
 ondragenter="handleDragEnter(event,this)">
            <span class="card-name">
                ${title}
            </span>
            <div class="card-img">
                <span>${src}</span>
<!--                <img src="${src}" draggable="false" alt="">-->
            </div>
        </div>`
        return tpl;
    }

    window.onload = function () {
        createDom(htmlArr);
    }
</script>

</html>
